
#include <stdio.h>
#include "input.h"
#include "device.h"
#include "task_manager.h"


static  sj_int8  key_input_device_open(struct file *file_node)
{
    return 0;
}

static  sj_int8  key_input_device_read(struct file *file_node,sj_uint8 *data ,sj_int32 len,sj_loff_t * loff)
{
    struct key_input_device_data *self_data = (struct key_input_device_data *)(file_node->private_data);
    struct key_process *proc=&self_data->proc;
    *data =proc->final_value;
    proc->final_value =0;
    return 0;
}

static  sj_int8  key_input_device_close(struct file *file_node)
{
    return 0;
}
static  sj_int8  key_input_device_poll(struct file *file_node,sj_int32 timeout)
{
    sj_int8 ret =0;
    struct key_input_device_data *self_data = (struct key_input_device_data *)(file_node->private_data);
    if(timeout<0)
    {
        timeout=0;
    }
    if(timeout==0)
    {
        goto out;
    }

    ret = sj_sem_wait(&self_data->sem,timeout);

out:
    return ret;
}

static sj_void key_input_timer_callback(sj_void *arg)
{
    struct key_input_device_data *self_data =(struct key_input_device_data *)arg;
    struct key_process *proc=&self_data->proc;
    struct key_input_gpio *input_gpio= self_data->gpio;
    sj_int8 i=0;
    sj_int8 now_value=0;

    for(i=0;i<self_data->key_num;i++)
    {
       struct gpio_pin *pin =&input_gpio[i].res;      
       if(sj_gpio_read(pin)!=input_gpio[i].default_val)
       {
           if(proc->process_state==0)
           {
                proc->process_state=1;
           }
           now_value =input_gpio[i].type_value;
           break;
       }
    }

    switch(proc->process_state)
    {
    case 0:
        if(proc->final_value)
        {
            if(++proc->time_count>10)
            {
                proc->final_value=0;
            }
        }
        proc->last_value =0;
        break;
    case 1:       
        proc->time_count=0;
        proc->process_state=2;
        proc->final_value=0;
        if(proc->last_value!=now_value)
        {
            proc->last_value=now_value;
        }
        break;
    case 2:
        if(proc->last_value==now_value)
        {
            proc->process_state=3;
        }
        else{
            proc->process_state=0;
        }
        break;
    case 3:
        if(now_value==0)
        {
            proc->process_state=0;
            proc->final_value=proc->last_value;
            proc->time_count=0;
        }
        if(++proc->time_count>10)
        {
            proc->process_state=4;
        }
        break;
    case 4:
        if(now_value==0)
        {
            proc->time_count=0;
            proc->process_state=0;
            proc->final_value=proc->last_value+KEY_LONG_VALUE_OFFSET;
        }
        break;
    default:
        break;
    }
    if(proc->final_value)
    {
        sj_sem_post(&self_data->sem);
    }
}

static sj_int8 key_input_device_probe(struct device *dev)
{
    sj_int8 ret =0;
    sj_int8 i=0;
    struct key_input_device_data *self_data =(struct key_input_device_data *)dev->private_data;
    if(!self_data)
    {
        ret =-1;
        goto out;
    }
    struct key_input_gpio *input_gpio= self_data->gpio;
    for(i=0;i<self_data->key_num;i++)
    {

        struct gpio_pin *pin =&input_gpio[i].res;
        struct rcc_apb_periph *apb= &input_gpio[i].rcc_apb;

        sj_gpio_clock_config(apb);

        sj_gpio_init(pin);

    }

    sj_sem_create(&self_data->sem,0);

    if(self_data->tim_num>=0 &&self_data->call_id>=0)
    {
        nvic_set_tim_callback(self_data->tim_num,self_data->call_id,key_input_timer_callback,self_data);
    }

out:
    return ret;
}

static sj_int8 key_input_device_ioctl(struct file *file_node,sj_int8 cmd ,sj_uint8 *data)
{
    sj_int8 ret =0;

    switch(cmd)
    {

        default:
            break;
    }

    return ret;
}

static struct file_operations key_input_opt =
{
    key_input_device_open,
    key_input_device_close,
    NULL,
    key_input_device_read,
    NULL,
    NULL,
    key_input_device_poll,
    key_input_device_ioctl,
};

static struct device_id_table key_input_id_table[]=
{
    {"input"},
    {NULL}
};

static struct device_driver key_input_driver={
    "input",
    key_input_id_table,
    &key_input_opt,
    key_input_device_probe,
    NULL,
    NULL,
    NULL,
    NULL,
};


static DRIVER_MODULE_INIT(key_input_driver)

